<template>
  <div class="page">
    <div id="3dcanvs"></div>
    <div class="btn" @click="animateCamera({ x: 0, y: 0, z: 0 }, { x: 100, y: 0, z: 10 })">卧室</div>
    <div class="btn" @click="animateCamera({ x: 0, y: 0, z: 0 }, { x: 200, y: 0, z: 10 })">客厅</div>
    <div v-for="(point, index) in roorms[0].interactivePoints" 
    :key="index" :class="[`point-${point.key}`]">
      <p class="p1">{{ point.value }}</p>
    </div>
  </div>
</template>

<script setup>
import { nextTick, onMounted, reactive } from 'vue'
import * as THREE from 'three';
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 引入tween动画库
import * as TWEEN from '@tweenjs/tween.js'

let roorms = reactive([
  {
    name: '客厅',
    interactivePoints: [
      {
        key: 'tv',
        value: '电视',
        cover: "img/bg.png",
        position: new THREE.Vector3(-8, 2, -15),
      },
      {
        key: 'art',
        value: '艺术品',
        cover: "img/bg2.png",
        position: new THREE.Vector3(10.5, 0, -15),
      },
    ]
  }
])
//设置场景宽高
const size = {
  width: window.innerWidth,
  height: window.innerHeight
}
//场景
const scene = new THREE.Scene();
//相机
const camera = new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
camera.position.set(10, 0, 0)
scene.add(camera);
//渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(size.width, size.height);
renderer.setClearColor(0x000000, 1); //设置背景颜色
renderer.setPixelRatio(window.devicePixelRatio); //设置 canvas 的像素比为当前设备的屏幕像素比，避免高分屏下出现模糊情况。



//创建多个房间以及环境贴图
//创建球体
let arr = ['img/bg.png', 'img/bg2.png', 'img/bg.png']
for (let i = 0; i < 3; i++) {
  const sphereGeometry = new THREE.SphereGeometry(50, 50, 50);
  const textureLoader = new THREE.TextureLoader();
  const sphereMaterial = new THREE.MeshBasicMaterial({
    map: textureLoader.load(arr[i]),
    side: THREE.DoubleSide,
  });
  const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  sphere.name = `sphere${i}`
  sphere.position.set(0 + i * 100, 0, 0);
  sphere.geometry.scale(1, 1, -1);
  scene.add(sphere);
}

//设置相机移动漫游
//限制缩放

let controls = new OrbitControls(camera, renderer.domElement);
// 转动惯性（阻尼）
controls.enableDamping = true;
controls.dampingFactor = 0.1;
//设置缩放
controls.maxDistance = 5;

// const dir = new THREE.Vector3();
// // 获取相机的视线方向
// camera.getWorldDirection(dir);
//归一化后的向量 相当于 相机的位置减去相机的目标位置(position-lookAt)再进行归一化normalize() 

function animateCamera(position, target) {
  let tween = new TWEEN.Tween({
    px: camera.position.x, // 起始相机位置x
    py: camera.position.y, // 起始相机位置y
    pz: camera.position.z, // 起始相机位置z
    tx: controls.target.x, // 控制点的中心点x 起始目标位置x
    ty: controls.target.y, // 控制点的中心点y 起始目标位置y
    tz: controls.target.z // 控制点的中心点z 起始目标位置z
  })
  tween.to({
    px: position.x,
    py: position.y,
    pz: position.z,
    tx: 100,
    ty: 100,
    tz: 100
  }, 500)
  tween.to({
    px: 100,
    py: 100,
    pz: 100,
    tx: target.x,
    ty: target.y,
    tz: target.z
  }, 1000)
  tween.onUpdate(function () {
    camera.position.x = this._object.px
    camera.position.y = this._object.py
    camera.position.z = this._object.pz
    controls.target.x = this._object.tx
    controls.target.y = this._object.ty
    controls.target.z = this._object.tz
    controls.update()
  })
  tween.easing(TWEEN.Easing.Cubic.InOut)
  tween.start()
}

// 页面缩放事件监听
window.addEventListener("resize", () => {
  size.width = window.innerWidth;
  size.height = window.innerHeight;
  // 更新渲染
  renderer.setSize(size.width, size.height);
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  // 更新相机
  camera.aspect = size.width / size.height;
  camera.updateProjectionMatrix();
});

// 渲染函数 
function render() {
  controls && controls.update();
  TWEEN && TWEEN.update();
  renderer.render(scene, camera); //执行渲染操作
  requestAnimationFrame(render);//请求再次执行渲染函数render，渲染下一帧
}
render();

async function increment() {
  await nextTick()
  // DOM 此时已经更新
  document.getElementById("3dcanvs").appendChild(renderer.domElement);
}
onMounted(() => {
  increment()
})

</script>

<style lang="scss" scoped>
.page {

  & .btn {
    position: fixed;
    z-index: 100;
    right: 20px;
    top: 200px;
    background-color: #fff;
    font-size: 20px;
    border-radius: 10px;
    padding: 10px 20px;
    cursor: pointer;
  }

  & .btn:nth-of-type(2) {
    top: 300px;
  }
  & .point-tv{
    width: 200px;
  }
}
</style>
